"""
态势对象业务逻辑服务层
"""
import json
import csv
import io
import yaml
import xml.etree.ElementTree as ET
import xml.dom.minidom
from typing import List, Optional, Dict, Any
from uuid import UUID
from datetime import datetime
import asyncio
from functools import wraps
from sqlalchemy import select, func, or_, and_, text
from sqlalchemy.ext.asyncio import AsyncSession

from src.situation.models import SituationObject
from src.situation.schemas import (
    SituationObjectCreate,
    SituationObjectUpdate,
    SituationObjectResponse,
    SituationObjectListResponse,
    SituationObjectFilter,
    ObjectType,
    StatisticsResponse,
    EquipmentCategoryResponse,
)
# 使用独立的 logger 导入，避免触发 src.__init__ 的图数据库初始化
from src.utils.logging_config import logger


def map_legacy_object_type(obj):
    """
    映射旧的对象类型到新的类型

    Args:
        obj: 数据库对象或字典

    Returns:
        映射后的对象
    """
    # 定义旧类型到新类型的映射
    type_mapping = {
        'weapon': 'land_target',
        'vessel': 'sea_target',
        'sensor': 'observation_equipment',
        'aircraft': 'observation_equipment',
        'vehicle': 'land_target'
    }

    if hasattr(obj, 'object_type') and obj.object_type in type_mapping:
        old_type = obj.object_type
        obj.object_type = type_mapping[old_type]
        logger.info(f"[调试] 映射旧类型 {old_type} -> {obj.object_type}")

    return obj


def retry_on_database_error(max_retries: int = 3, delay: float = 0.1):
    """
    数据库操作重试装饰器，用于处理随机性的数据库错误
    """
    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            last_exception = None

            for attempt in range(max_retries):
                try:
                    return await func(*args, **kwargs)
                except Exception as e:
                    last_exception = e
                    error_str = str(e).lower()

                    # 只对特定的数据库错误进行重试
                    if any(keyword in error_str for keyword in [
                        "does not exist",
                        "undefined table",
                        "connection",
                        "timeout",
                        "deadlock"
                    ]):
                        logger.warning(f"[数据库重试] {func.__name__} 第 {attempt + 1} 次尝试失败: {e}")
                        if attempt < max_retries - 1:
                            await asyncio.sleep(delay * (attempt + 1))
                            continue

                    # 对于其他错误，直接抛出
                    break

            # 重试次数用完或非重试错误，抛出最后的异常
            raise last_exception

        return wrapper
    return decorator


class SituationService:
    """态势对象服务类"""

    @staticmethod
    @retry_on_database_error(max_retries=3, delay=0.1)
    async def create_object(db: AsyncSession, obj_data: SituationObjectCreate, user: Optional[str] = None) -> SituationObjectResponse:
        """
        创建态势对象

        Args:
            db: 数据库会话
            obj_data: 创建数据
            user: 创建用户

        Returns:
            创建后的对象
        """
        logger.info(f"[调试] 开始创建态势对象: name={obj_data.name}, code={obj_data.code}")

        # 首先检查表是否存在
        if not await SituationService._check_table_exists(db):
            logger.error("[调试] situation_objects 表不存在，无法创建对象")
            raise ValueError("数据库表不存在，请联系管理员初始化数据库")

        try:
            # 检查 code 是否已存在
            if obj_data.code:
                logger.info(f"[调试] 检查 code 唯一性: {obj_data.code}")
                existing_stmt = select(SituationObject).where(
                    and_(SituationObject.code == obj_data.code, SituationObject.is_deleted == False)
                )
                existing_result = await db.execute(existing_stmt)
                existing_obj = existing_result.scalar_one_or_none()

                if existing_obj:
                    logger.warning(f"[调试] code {obj_data.code} 已存在，对象ID: {existing_obj.id}")
                    raise ValueError(f"编码 '{obj_data.code}' 已存在，请使用不同的编码")

            # 转换 type_specific_data 为 dict
            type_specific_dict = obj_data.type_specific_data
            if hasattr(type_specific_dict, "model_dump"):
                type_specific_dict = type_specific_dict.model_dump(exclude_none=True)

            # 记录装备类别信息
            if obj_data.object_type.value == "observation_equipment":
                equipment_category = type_specific_dict.get("equipment_category") if isinstance(type_specific_dict, dict) else None
                logger.info(f"[调试] 观测装备装备类别: {equipment_category}")
                logger.info(f"[调试] 类型特定数据: {type_specific_dict}")

            logger.info(f"[调试] 开始创建数据库对象")
            # 创建数据库对象
            db_obj = SituationObject(
                object_type=obj_data.object_type.value,
                equipment_category=obj_data.equipment_category,
                name=obj_data.name,
                code=obj_data.code,
                model=obj_data.model,
                organization=obj_data.organization,
                deployment_status=obj_data.deployment_status.value if obj_data.deployment_status else None,
                detection_range=obj_data.detection_range,
                response_time=obj_data.response_time,
                accuracy=obj_data.accuracy,
                perception_capability=obj_data.perception_capability,
                communication_capability=obj_data.communication_capability,
                applicable_scenarios=obj_data.applicable_scenarios,
                location=obj_data.location,
                type_specific_data=type_specific_dict or {},
                extra_metadata=obj_data.extra_metadata or {},
                tags=obj_data.tags or [],
                created_by=user,
            )

            logger.info(f"[调试] 添加对象到数据库会话")
            db.add(db_obj)

            logger.info(f"[调试] 提交数据库事务")
            await db.commit()
            await db.refresh(db_obj)

            logger.info(f"创建态势对象成功: {db_obj.id}, type={db_obj.object_type}, name={db_obj.name}, code={db_obj.code}")
            # 处理旧类型数据
            map_legacy_object_type(db_obj)
            return SituationObjectResponse.model_validate(db_obj)

        except ValueError as ve:
            logger.error(f"[调试] 创建对象失败 - 业务逻辑错误: {ve}")
            raise ve
        except Exception as e:
            logger.error(f"[调试] 创建对象失败 - 数据库错误: {type(e).__name__}: {e}")
            await db.rollback()

            # 解析数据库错误，提供更友好的错误信息
            error_str = str(e).lower()
            if "duplicate key" in error_str and "code" in error_str:
                raise ValueError(f"编码 '{obj_data.code}' 已存在，请使用不同的编码")
            elif "duplicate key" in error_str:
                raise ValueError("数据重复，请检查唯一性约束字段")
            elif "null" in error_str and "not null" in error_str:
                raise ValueError("必填字段不能为空")
            else:
                raise ValueError(f"创建失败: {str(e)}")

    @staticmethod
    async def get_object(db: AsyncSession, object_id: UUID) -> Optional[SituationObjectResponse]:
        """
        获取单个态势对象

        Args:
            db: 数据库会话
            object_id: 对象ID

        Returns:
            对象详情或 None
        """
        stmt = select(SituationObject).where(and_(SituationObject.id == object_id, SituationObject.is_deleted == False))  # noqa: E712
        result = await db.execute(stmt)
        db_obj = result.scalar_one_or_none()

        if db_obj:
            # 处理旧类型数据
            map_legacy_object_type(db_obj)
            return SituationObjectResponse.model_validate(db_obj)
        return None

    @staticmethod
    async def _check_table_exists(db: AsyncSession) -> bool:
        """检查表是否存在"""
        try:
            from sqlalchemy import text
            result = await db.execute(text("""
                SELECT EXISTS (
                    SELECT FROM information_schema.tables
                    WHERE table_schema = 'public'
                    AND table_name = 'situation_objects'
                )
            """))
            exists = result.scalar()
            logger.info(f"[调试] situation_objects 表存在性检查: {exists}")
            return exists
        except Exception as e:
            logger.error(f"[调试] 检查表存在性失败: {e}")
            return False

    @staticmethod
    @retry_on_database_error(max_retries=3, delay=0.1)
    async def list_objects(db: AsyncSession, page: int = 1, page_size: int = 20, filters: Optional[SituationObjectFilter] = None) -> SituationObjectListResponse:
        """
        获取态势对象列表（分页、筛选）

        Args:
            db: 数据库会话
            page: 页码
            page_size: 每页数量
            filters: 筛选条件

        Returns:
            分页列表
        """
        logger.info(f"[调试] 开始获取态势对象列表: page={page}, page_size={page_size}")
        logger.info(f"[调试] 筛选条件: {filters}")

        # 首先检查表是否存在
        if not await SituationService._check_table_exists(db):
            logger.error("[调试] situation_objects 表不存在，返回空结果")
            return SituationObjectListResponse(total=0, items=[], page=page, page_size=page_size)

        try:
            # 构建查询条件
            conditions = [SituationObject.is_deleted == False]  # noqa: E712
            logger.info(f"[调试] 基础条件构建完成: {len(conditions)} 个条件")

            if filters:
                logger.info(f"[调试] 开始处理筛选条件")
                if filters.object_type:
                    logger.info(f"[调试] 添加对象类型筛选: {filters.object_type.value}")
                    conditions.append(SituationObject.object_type == filters.object_type.value)
                if filters.equipment_category:
                    logger.info(f"[调试] 添加装备类别筛选: {filters.equipment_category}")
                    conditions.append(SituationObject.equipment_category == filters.equipment_category)
                if filters.deployment_status:
                    logger.info(f"[调试] 添加部署状态筛选: {filters.deployment_status.value}")
                    conditions.append(SituationObject.deployment_status == filters.deployment_status.value)
                if filters.organization:
                    logger.info(f"[调试] 添加所属单位筛选: {filters.organization}")
                    conditions.append(SituationObject.organization.ilike(f"%{filters.organization}%"))
                if filters.search:
                    logger.info(f"[调试] 添加搜索条件: {filters.search}")
                    search_condition = or_(SituationObject.name.ilike(f"%{filters.search}%"), SituationObject.code.ilike(f"%{filters.search}%"))
                    conditions.append(search_condition)
                if filters.tags:
                    logger.info(f"[调试] 添加标签筛选: {filters.tags}")
                    # PostgreSQL 数组包含查询
                    for tag in filters.tags:
                        conditions.append(SituationObject.tags.contains([tag]))
                logger.info(f"[调试] 筛选条件处理完成，总共 {len(conditions)} 个条件")

            # 查询总数
            logger.info(f"[调试] 开始构建总数查询")
            count_stmt = select(func.count()).select_from(SituationObject).where(and_(*conditions))
            logger.info(f"[调试] 总数查询语句: {count_stmt}")

            total_result = await db.execute(count_stmt)
            total = total_result.scalar()
            logger.info(f"[调试] 查询到总数: {total}")

            # 查询分页数据
            offset = (page - 1) * page_size
            logger.info(f"[调试] 计算偏移量: offset={offset}")

            stmt = select(SituationObject).where(and_(*conditions)).order_by(SituationObject.created_at.desc()).offset(offset).limit(page_size)
            logger.info(f"[调试] 分页查询语句: {stmt}")

            logger.info(f"[调试] 开始执行分页查询")
            result = await db.execute(stmt)
            items = result.scalars().all()
            logger.info(f"[调试] 查询到 {len(items)} 条记录")

            logger.info(f"[调试] 开始转换为响应对象")
            response_items = []

            for i, item in enumerate(items):
                try:
                    # 处理旧类型数据
                    map_legacy_object_type(item)

                    response_item = SituationObjectResponse.model_validate(item)
                    response_items.append(response_item)
                    if i < 3:  # 只记录前3个用于调试
                        logger.info(f"[调试] 转换第 {i+1} 个对象成功: {item.name}")
                except Exception as e:
                    logger.error(f"[调试] 转换第 {i+1} 个对象失败: {e}, item={item}")
                    raise

            logger.info(f"[调试] 所有对象转换完成，共 {len(response_items)} 个")

            result = SituationObjectListResponse(total=total, items=response_items, page=page, page_size=page_size)
            logger.info(f"[调试] 响应对象创建成功: total={total}, actual_items={len(response_items)}")

            return result

        except Exception as e:
            logger.error(f"[调试] list_objects 发生异常: {type(e).__name__}: {e}")
            import traceback
            logger.error(f"[调试] 异常堆栈: {traceback.format_exc()}")
            raise

    @staticmethod
    async def update_object(db: AsyncSession, object_id: UUID, obj_data: SituationObjectUpdate, user: Optional[str] = None) -> Optional[SituationObjectResponse]:
        """
        更新态势对象

        Args:
            db: 数据库会话
            object_id: 对象ID
            obj_data: 更新数据
            user: 更新用户

        Returns:
            更新后的对象或 None
        """
        logger.info(f"[调试] 开始更新态势对象: {object_id}")

        try:
            stmt = select(SituationObject).where(and_(SituationObject.id == object_id, SituationObject.is_deleted == False))  # noqa: E712
            result = await db.execute(stmt)
            db_obj = result.scalar_one_or_none()

            if not db_obj:
                logger.warning(f"[调试] 要更新的对象不存在: {object_id}")
                return None

            # 检查如果更新 code，新的 code 是否已存在
            if obj_data.code and obj_data.code != db_obj.code:
                logger.info(f"[调试] 检查新 code 的唯一性: {obj_data.code}")
                existing_stmt = select(SituationObject).where(
                    and_(
                        SituationObject.code == obj_data.code,
                        SituationObject.id != object_id,
                        SituationObject.is_deleted == False
                    )
                )
                existing_result = await db.execute(existing_stmt)
                existing_obj = existing_result.scalar_one_or_none()

                if existing_obj:
                    logger.warning(f"[调试] 新 code {obj_data.code} 已存在，对象ID: {existing_obj.id}")
                    raise ValueError(f"编码 '{obj_data.code}' 已存在，请使用不同的编码")

            # 更新字段（仅更新非 None 的字段）
            update_data = obj_data.model_dump(exclude_unset=True)
            logger.info(f"[调试] 更新字段: {list(update_data.keys())}")

            # 更新字段（仅更新非 None 的字段）
            for field, value in update_data.items():
                if field == "object_type" and value:
                    setattr(db_obj, field, value.value)
                elif field == "deployment_status" and value:
                    setattr(db_obj, field, value.value)
                elif field == "type_specific_data" and value:
                    # 合并 type_specific_data
                    current_data = db_obj.type_specific_data or {}
                    current_data.update(value)
                    setattr(db_obj, field, current_data)
                    logger.info(f"[调试] 更新类型特定数据: {current_data}")
                elif value is not None:
                    setattr(db_obj, field, value)
                    logger.info(f"[调试] 更新字段 {field}: {value}")

            db_obj.updated_by = user
            db_obj.updated_at = datetime.utcnow()

            logger.info(f"[调试] 提交更新事务")
            await db.commit()
            await db.refresh(db_obj)

            logger.info(f"更新态势对象成功: {db_obj.id}")
            # 处理旧类型数据
            map_legacy_object_type(db_obj)
            return SituationObjectResponse.model_validate(db_obj)

        except ValueError as ve:
            logger.error(f"[调试] 更新对象失败 - 业务逻辑错误: {ve}")
            await db.rollback()
            raise ve
        except Exception as e:
            logger.error(f"[调试] 更新对象失败 - 系统错误: {type(e).__name__}: {e}")
            await db.rollback()

            # 解析数据库错误，提供更友好的错误信息
            error_str = str(e).lower()
            if "duplicate key" in error_str and "code" in error_str:
                raise ValueError(f"编码 '{obj_data.code}' 已存在，请使用不同的编码")
            elif "duplicate key" in error_str:
                raise ValueError("数据重复，请检查唯一性约束字段")
            elif "null" in error_str and "not null" in error_str:
                raise ValueError("必填字段不能为空")
            else:
                raise ValueError(f"更新失败: {str(e)}")

    @staticmethod
    @retry_on_database_error(max_retries=3, delay=0.1)
    async def delete_object(db: AsyncSession, object_id: UUID, user: Optional[str] = None) -> bool:
        """
        删除态势对象（软删除）

        Args:
            db: 数据库会话
            object_id: 对象ID
            user: 删除用户

        Returns:
            是否成功
        """
        logger.info(f"[调试] 开始删除态势对象: {object_id}")

        # 首先检查表是否存在
        if not await SituationService._check_table_exists(db):
            logger.error("[调试] situation_objects 表不存在，无法删除对象")
            raise ValueError("数据库表不存在，请联系管理员初始化数据库")

        try:
            stmt = select(SituationObject).where(and_(SituationObject.id == object_id, SituationObject.is_deleted == False))  # noqa: E712
            result = await db.execute(stmt)
            db_obj = result.scalar_one_or_none()

            if not db_obj:
                logger.warning(f"[调试] 要删除的对象不存在: {object_id}")
                return False

            db_obj.is_deleted = True
            db_obj.deleted_at = datetime.utcnow()
            db_obj.updated_by = user

            await db.commit()
            logger.info(f"删除态势对象成功: {object_id}")
            return True

        except Exception as e:
            logger.error(f"[调试] 删除对象失败: {type(e).__name__}: {e}")
            await db.rollback()
            raise ValueError(f"删除失败: {str(e)}")

    @staticmethod
    async def batch_delete(db: AsyncSession, object_ids: List[UUID], user: Optional[str] = None) -> int:
        """
        批量删除态势对象

        Args:
            db: 数据库会话
            object_ids: 对象ID列表
            user: 删除用户

        Returns:
            删除数量
        """
        stmt = select(SituationObject).where(and_(SituationObject.id.in_(object_ids), SituationObject.is_deleted == False))  # noqa: E712
        result = await db.execute(stmt)
        objects = result.scalars().all()

        count = 0
        for obj in objects:
            obj.is_deleted = True
            obj.deleted_at = datetime.utcnow()
            obj.updated_by = user
            count += 1

        await db.commit()
        logger.info(f"批量删除态势对象成功: {count} 个")
        return count

    @staticmethod
    async def get_statistics(db: AsyncSession) -> StatisticsResponse:
        """
        获取统计信息

        Returns:
            统计数据
        """
        # 总数
        total_stmt = select(func.count()).select_from(SituationObject).where(SituationObject.is_deleted == False)  # noqa: E712
        total_result = await db.execute(total_stmt)
        total_count = total_result.scalar()

        # 按类型统计
        type_stmt = select(SituationObject.object_type, func.count()).where(SituationObject.is_deleted == False).group_by(SituationObject.object_type)  # noqa: E712
        type_result = await db.execute(type_stmt)
        by_type = {row[0]: row[1] for row in type_result.all()}

        # 按状态统计
        status_stmt = select(SituationObject.deployment_status, func.count()).where(SituationObject.is_deleted == False).group_by(SituationObject.deployment_status)  # noqa: E712
        status_result = await db.execute(status_stmt)
        by_status = {row[0] or "未知": row[1] for row in status_result.all()}

        # 按单位统计
        org_stmt = select(SituationObject.organization, func.count()).where(SituationObject.is_deleted == False).group_by(SituationObject.organization).order_by(func.count().desc()).limit(10)  # noqa: E712
        org_result = await db.execute(org_stmt)
        by_organization = {row[0] or "未知": row[1] for row in org_result.all()}

        return StatisticsResponse(total_count=total_count, by_type=by_type, by_status=by_status, by_organization=by_organization)

    @staticmethod
    async def import_from_json(db: AsyncSession, json_data: str, user: Optional[str] = None) -> Dict[str, Any]:
        """从 JSON 批量导入"""
        try:
            data = json.loads(json_data)
            if not isinstance(data, list):
                data = [data]

            success_count = 0
            errors = []

            for idx, item in enumerate(data):
                try:
                    # 验证数据格式
                    validated_data = SituationService._validate_import_data(item, "JSON")
                    obj_create = SituationObjectCreate(**validated_data)
                    await SituationService.create_object(db, obj_create, user)
                    success_count += 1
                except Exception as e:
                    errors.append({"index": idx, "error": str(e), "data": item})

            return {"success_count": success_count, "error_count": len(errors), "errors": errors}
        except Exception as e:
            logger.error(f"JSON 导入失败: {e}")
            raise ValueError(f"JSON 解析失败: {e}")

    @staticmethod
    async def import_from_csv(db: AsyncSession, csv_data: str, user: Optional[str] = None) -> Dict[str, Any]:
        """从 CSV 批量导入"""
        try:
            csv_file = io.StringIO(csv_data)
            reader = csv.DictReader(csv_file)

            success_count = 0
            errors = []

            for idx, row in enumerate(reader):
                try:
                    # 转换 CSV 行为对象数据
                    obj_data = SituationService._parse_csv_row(row)
                    # 验证数据格式
                    validated_data = SituationService._validate_import_data(obj_data, "CSV")
                    obj_create = SituationObjectCreate(**validated_data)
                    await SituationService.create_object(db, obj_create, user)
                    success_count += 1
                except Exception as e:
                    errors.append({"index": idx, "error": str(e), "data": row})

            return {"success_count": success_count, "error_count": len(errors), "errors": errors}
        except Exception as e:
            logger.error(f"CSV 导入失败: {e}")
            raise ValueError(f"CSV 解析失败: {e}")

    @staticmethod
    def _parse_csv_row(row: Dict[str, str]) -> Dict[str, Any]:
        """解析 CSV 行数据"""
        obj_data = {}
        for key, value in row.items():
            if not value or value.strip() == "":
                continue

            # 处理特殊字段
            if key in ["applicable_scenarios", "tags"]:
                obj_data[key] = [v.strip() for v in value.split(",") if v.strip()]
            elif key in ["perception_capability", "communication_capability", "location", "type_specific_data", "extra_metadata"]:
                try:
                    obj_data[key] = json.loads(value)
                except Exception:
                    obj_data[key] = {}
            elif key in ["detection_range", "response_time", "accuracy"]:
                try:
                    obj_data[key] = float(value)
                except ValueError:
                    raise ValueError(f"字段 {key} 必须是有效的数字: {value}")
            else:
                obj_data[key] = value.strip() if hasattr(value, 'strip') else value

        # 验证必填字段
        if not obj_data.get("name"):
            raise ValueError("名称字段是必填的")
        if not obj_data.get("object_type"):
            raise ValueError("对象类型字段是必填的")

        return obj_data

    @staticmethod
    def _validate_import_data(obj_data: Dict[str, Any], format_name: str) -> Dict[str, Any]:
        """验证导入数据的格式和内容"""
        errors = []

        # 验证必填字段
        if not obj_data.get("name"):
            errors.append("名称字段是必填的")
        if not obj_data.get("object_type"):
            errors.append("对象类型字段是必填的")

        # 验证对象类型
        if obj_data.get("object_type"):
            valid_types = ["observation_equipment", "infrastructure", "sea_target", "land_target"]
            if obj_data["object_type"] not in valid_types:
                errors.append(f"无效的对象类型: {obj_data['object_type']}，支持的类型: {', '.join(valid_types)}")

        # 验证部署状态
        if obj_data.get("deployment_status"):
            valid_statuses = ["已部署", "待部署", "维护中", "退役"]
            if obj_data["deployment_status"] not in valid_statuses:
                errors.append(f"无效的部署状态: {obj_data['deployment_status']}，支持的状态: {', '.join(valid_statuses)}")

        # 验证数值字段
        numeric_fields = ["detection_range", "response_time"]
        for field in numeric_fields:
            if field in obj_data and obj_data[field] is not None:
                try:
                    obj_data[field] = float(obj_data[field])
                    if obj_data[field] < 0:
                        errors.append(f"字段 {field} 不能为负数")
                except (ValueError, TypeError):
                    errors.append(f"字段 {field} 必须是有效的数字")

        # 验证精度字段
        if "accuracy" in obj_data and obj_data["accuracy"] is not None:
            try:
                obj_data["accuracy"] = float(obj_data["accuracy"])
                if not (0 <= obj_data["accuracy"] <= 100):
                    errors.append("精度必须在0-100之间")
            except (ValueError, TypeError):
                errors.append("精度必须是有效的数字")

        # 验证数组字段
        array_fields = ["applicable_scenarios", "tags"]
        for field in array_fields:
            if field in obj_data and obj_data[field] is not None:
                if isinstance(obj_data[field], str):
                    # 如果是字符串，尝试按逗号分割
                    obj_data[field] = [v.strip() for v in obj_data[field].split(",") if v.strip()]
                elif isinstance(obj_data[field], list):
                    # 确保列表元素都是字符串
                    obj_data[field] = [str(v).strip() for v in obj_data[field] if v is not None]
                else:
                    obj_data[field] = []

        # 验证字典字段
        dict_fields = ["perception_capability", "communication_capability", "location", "type_specific_data", "extra_metadata"]
        for field in dict_fields:
            if field in obj_data and obj_data[field] is not None:
                if isinstance(obj_data[field], dict):
                    # 清理字典中的None值
                    obj_data[field] = {k: v for k, v in obj_data[field].items() if v is not None}
                else:
                    # 尝试解析JSON字符串
                    try:
                        if isinstance(obj_data[field], str):
                            obj_data[field] = json.loads(obj_data[field])
                        else:
                            obj_data[field] = {"value": str(obj_data[field])}
                    except Exception:
                        obj_data[field] = {}

        # 清理字符串字段
        string_fields = ["name", "code", "model", "organization"]
        for field in string_fields:
            if field in obj_data and obj_data[field] is not None:
                obj_data[field] = str(obj_data[field]).strip()
                if not obj_data[field]:
                    obj_data[field] = None

        if errors:
            raise ValueError(f"数据验证失败: {'; '.join(errors)}")

        return obj_data

    @staticmethod
    async def import_from_xml(db: AsyncSession, xml_data: str, user: Optional[str] = None) -> Dict[str, Any]:
        """从 XML 批量导入"""
        try:
            root = ET.fromstring(xml_data)

            # 支持两种XML格式：
            # 1. <objects><object>...</object><object>...</object></objects>
            # 2. <situation_objects><situation_object>...</situation_object></situation_objects>

            # 查找对象节点
            objects_node = root.find('objects')
            if objects_node is None:
                objects_node = root.find('situation_objects')

            if objects_node is None:
                # 如果没有父容器，直接在根节点下查找object节点
                object_nodes = root.findall('object') + root.findall('situation_object')
            else:
                object_nodes = objects_node.findall('object') + objects_node.findall('situation_object')

            if not object_nodes:
                raise ValueError("XML中未找到有效的对象数据，请检查XML格式")

            success_count = 0
            errors = []

            for idx, obj_node in enumerate(object_nodes):
                try:
                    obj_data = SituationService._parse_xml_node(obj_node)
                    # 验证数据格式
                    validated_data = SituationService._validate_import_data(obj_data, "XML")
                    obj_create = SituationObjectCreate(**validated_data)
                    await SituationService.create_object(db, obj_create, user)
                    success_count += 1
                except Exception as e:
                    errors.append({"index": idx, "error": str(e), "node": ET.tostring(obj_node, encoding='unicode')})

            return {"success_count": success_count, "error_count": len(errors), "errors": errors}
        except ET.ParseError as e:
            logger.error(f"XML 解析失败: {e}")
            raise ValueError(f"XML 格式错误: {e}")
        except Exception as e:
            logger.error(f"XML 导入失败: {e}")
            raise ValueError(f"XML 导入失败: {e}")

    @staticmethod
    def _parse_xml_node(node: ET.Element) -> Dict[str, Any]:
        """解析 XML 对象节点"""
        obj_data = {}

        # 解析基础字段
        for child in node:
            tag_name = child.tag.lower()
            text_value = child.text.strip() if child.text else ""

            if not text_value:
                continue

            # 处理特殊字段
            if tag_name in ["applicable_scenarios", "tags"]:
                # 支持两种格式：<tags>标签1,标签2,标签3</tags> 或 <tags><tag>标签1</tag><tag>标签2</tag></tags>
                if len(list(child)) > 0:  # 子节点格式
                    obj_data[tag_name] = [subchild.text.strip() for subchild in child if subchild.text and subchild.text.strip()]
                else:  # 逗号分隔格式
                    obj_data[tag_name] = [v.strip() for v in text_value.split(",")]
            elif tag_name in ["perception_capability", "communication_capability", "location", "type_specific_data", "extra_metadata"]:
                # 复杂对象字段，期望是JSON格式的字符串或子节点结构
                if len(list(child)) > 0:  # 子节点格式
                    child_dict = {}
                    for subchild in child:
                        if subchild.text and subchild.text.strip():
                            child_dict[subchild.tag] = subchild.text.strip()
                    obj_data[tag_name] = child_dict
                else:  # JSON字符串格式
                    try:
                        obj_data[tag_name] = json.loads(text_value)
                    except Exception:
                        obj_data[tag_name] = {"value": text_value}
            elif tag_name in ["detection_range", "response_time", "accuracy"]:
                try:
                    obj_data[tag_name] = float(text_value)
                except ValueError:
                    obj_data[tag_name] = 0.0
            else:
                obj_data[tag_name] = text_value

        return obj_data

    @staticmethod
    async def import_from_yaml(db: AsyncSession, yaml_data: str, user: Optional[str] = None) -> Dict[str, Any]:
        """从 YAML 批量导入"""
        try:
            data = yaml.safe_load(yaml_data)

            if not data:
                raise ValueError("YAML 文件为空或格式无效")

            # 支持多种YAML格式：
            # 1. 对象列表格式: [{obj1}, {obj2}, ...]
            # 2. 嵌套格式: {objects: [{obj1}, {obj2}]} 或 {situation_objects: [{obj1}, {obj2}]}
            # 3. 单个对象格式: {obj1}

            objects_list = []

            if isinstance(data, list):
                # 格式1：对象列表
                objects_list = data
            elif isinstance(data, dict):
                # 格式2：嵌套对象或单个对象
                if 'objects' in data:
                    objects_list = data['objects']
                elif 'situation_objects' in data:
                    objects_list = data['situation_objects']
                else:
                    # 格式3：单个对象
                    objects_list = [data]
            else:
                raise ValueError("不支持的YAML格式，请参考文档说明")

            if not isinstance(objects_list, list):
                objects_list = [objects_list]

            success_count = 0
            errors = []

            for idx, item in enumerate(objects_list):
                try:
                    if not isinstance(item, dict):
                        raise ValueError("对象必须是字典格式")

                    # 验证数据格式
                    validated_data = SituationService._validate_import_data(item, "YAML")
                    obj_create = SituationObjectCreate(**validated_data)
                    await SituationService.create_object(db, obj_create, user)
                    success_count += 1
                except Exception as e:
                    errors.append({"index": idx, "error": str(e), "data": item})

            return {"success_count": success_count, "error_count": len(errors), "errors": errors}
        except yaml.YAMLError as e:
            logger.error(f"YAML 解析失败: {e}")
            raise ValueError(f"YAML 格式错误: {e}")
        except Exception as e:
            logger.error(f"YAML 导入失败: {e}")
            raise ValueError(f"YAML 导入失败: {e}")

    @staticmethod
    async def export_to_json(db: AsyncSession, filters: Optional[SituationObjectFilter] = None) -> str:
        """导出为 JSON"""
        result = await SituationService.list_objects(db, page=1, page_size=10000, filters=filters)
        items_dict = [item.model_dump(mode="json") for item in result.items]
        return json.dumps(items_dict, ensure_ascii=False, indent=2, default=str)

    @staticmethod
    async def export_to_xml(db: AsyncSession, filters: Optional[SituationObjectFilter] = None) -> str:
        """导出为 XML"""
        result = await SituationService.list_objects(db, page=1, page_size=10000, filters=filters)

        # 创建XML根节点
        root = ET.Element("situation_objects")

        for item in result.items:
            obj_elem = ET.SubElement(root, "situation_object")

            # 添加基础字段
            fields = ["id", "object_type", "name", "code", "model", "organization", "deployment_status",
                     "detection_range", "response_time", "accuracy"]

            for field in fields:
                value = getattr(item, field, None)
                if value is not None:
                    field_elem = ET.SubElement(obj_elem, field)
                    field_elem.text = str(value)

            # 添加复杂字段
            complex_fields = ["perception_capability", "communication_capability", "location",
                            "type_specific_data", "extra_metadata"]

            for field in complex_fields:
                value = getattr(item, field, None)
                if value:
                    field_elem = ET.SubElement(obj_elem, field)
                    if isinstance(value, dict):
                        # 如果是字典，创建子节点
                        for key, val in value.items():
                            sub_elem = ET.SubElement(field_elem, key)
                            sub_elem.text = str(val) if val is not None else ""
                    else:
                        field_elem.text = str(value)

            # 添加数组字段
            array_fields = ["applicable_scenarios", "tags"]
            for field in array_fields:
                value = getattr(item, field, None)
                if value:
                    field_elem = ET.SubElement(obj_elem, field)
                    for item_val in value:
                        sub_elem = ET.SubElement(field_elem, "item")
                        sub_elem.text = str(item_val)

            # 添加时间戳字段
            timestamp_fields = ["created_at", "updated_at"]
            for field in timestamp_fields:
                value = getattr(item, field, None)
                if value:
                    field_elem = ET.SubElement(obj_elem, field)
                    field_elem.text = value.isoformat() if hasattr(value, 'isoformat') else str(value)

        # 格式化XML输出
        xml_str = ET.tostring(root, encoding='unicode')
        # 添加XML声明和格式化
        dom = xml.dom.minidom.parseString(xml_str)
        return dom.toprettyxml(indent="  ", encoding='unicode')

    @staticmethod
    async def export_to_yaml(db: AsyncSession, filters: Optional[SituationObjectFilter] = None) -> str:
        """导出为 YAML"""
        result = await SituationService.list_objects(db, page=1, page_size=10000, filters=filters)

        # 转换为字典格式
        objects_data = {
            "situation_objects": [item.model_dump(mode="json") for item in result.items]
        }

        return yaml.dump(objects_data, ensure_ascii=False, default_flow_style=False, allow_unicode=True, indent=2)

    @staticmethod
    async def export_to_csv(db: AsyncSession, filters: Optional[SituationObjectFilter] = None) -> str:
        """导出为 CSV"""
        result = await SituationService.list_objects(db, page=1, page_size=10000, filters=filters)

        if not result.items:
            return ""

        output = io.StringIO()
        # 定义 CSV 字段
        fieldnames = ["id", "object_type", "name", "code", "model", "organization", "deployment_status", "created_at", "updated_at"]
        writer = csv.DictWriter(output, fieldnames=fieldnames)
        writer.writeheader()

        for item in result.items:
            row = {field: getattr(item, field, "") for field in fieldnames}
            writer.writerow(row)

        return output.getvalue()

    @staticmethod
    def get_equipment_categories_by_type(object_type: str = None):
        """
        获取装备类别信息
        Args:
            object_type: 对象类型，如果为None则返回所有类型
        Returns:
            装备类别信息
        """
        from src.situation.schemas import get_all_equipment_categories, get_equipment_categories_by_type, EquipmentCategoriesListResponse

        if object_type:
            # 返回单个对象类型的装备类别
            return get_equipment_categories_by_type(object_type)
        else:
            # 返回所有对象类型的装备类别，包装在统一响应格式中
            all_categories = get_all_equipment_categories()
            return EquipmentCategoriesListResponse(categories=all_categories)
